﻿using LJ.Abstractions.Extensions;
using LJ.Abstractions.Reflection;
using LJ.WebApi.Abstractions.DynamicWebApi;
using LJ.WebApi.Abstractions.DynamicWebApi.Attributes;
using LJ.WebApi.Mvc.Pack;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace LJ.WebApi.Mvc.DynamicWebApi.Internal;

public class DynamicWebApiManager : IDynamicWebApiManager
{
    public ConcurrentBag<Type> DynamicWebApiControllerTypes { get; } = [];

    public ConcurrentDictionary<Type, DynamicWebApiAttribute?> DynamicWebApiAttributes { get; } = [];

    public ConcurrentDictionary<MethodInfo, DynamicWebApiMethodAttribute?> DynamicWebApiMethodAttributes { get; } = [];

    private readonly IReflectionManager _reflectionManager;

    public DynamicWebApiManager(IReflectionManager reflectionManager)
    {
        _reflectionManager = reflectionManager;

        var types = FindTypes();

        foreach (var type in types)
        {
           Add(type);
        }

    }


    private List<Type> FindTypes()
    {
        Type[] baseTypes = [typeof(IDynamicWebApiController)];
        return _reflectionManager.GetTypes(type => (baseTypes.Any(b => type.IsDeriveClassFrom(b))) && type.HasAttribute<DynamicWebApiAttribute>());
    }

    public void Add(Type dynamicWebApiControllerType)
    {
        DynamicWebApiControllerTypes.Add(dynamicWebApiControllerType);

        DynamicWebApiAttributes.TryAdd(dynamicWebApiControllerType, dynamicWebApiControllerType.GetCustomAttribute<DynamicWebApiAttribute>());

        var methodInfos = dynamicWebApiControllerType.GetMethods(BindingFlags.Public);
        foreach (var methodInfo in methodInfos)
        {
            DynamicWebApiMethodAttributes.TryAdd(methodInfo, methodInfo.GetCustomAttribute<DynamicWebApiMethodAttribute>());
        }
    }

    public bool IsApiController(Type type)
    {
        return DynamicWebApiControllerTypes.Contains(type);
    }

    public DynamicWebApiAttribute? GetDynamicWebApiAttribute(Type type)
    {
        return DynamicWebApiAttributes[type];
    }

    public DynamicWebApiMethodAttribute? GetDynamicWebApiMethodAttribute(MethodInfo methodInfo)
    {
        return DynamicWebApiMethodAttributes[methodInfo];
    }
}
